/*******************************************************************************
 * Copyright (c) 2009-2011 ETCORE Labs. All rights reserved. 
 * 
 * This software is the confidential and proprietary information of ETCORE Labs.
 * You shall not disclose such confidential information and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with ETCORE Labs. 
 * 
 * Support can be obtained from support forums at:  http://www.etcore.com/
 * /
 *******************************************************************************/
package etcore.webapp.grouptalk.reminder.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import etcore.webapp.grouptalk.common.action.AbstractAction;
import etcore.webapp.grouptalk.common.config.Config;
import etcore.webapp.grouptalk.common.config.MessageNamespaces;
import etcore.webapp.grouptalk.common.config.Messages;
import etcore.webapp.grouptalk.common.config.PageConstants;
import etcore.webapp.grouptalk.common.object.Directory;
import etcore.webapp.grouptalk.common.object.Group;
import etcore.webapp.grouptalk.common.object.Message;
import etcore.webapp.grouptalk.common.object.Topic;
import etcore.webapp.grouptalk.common.service.DirectoryService;
import etcore.webapp.grouptalk.common.service.GroupService;
import etcore.webapp.grouptalk.common.service.MessageService;
import etcore.webapp.grouptalk.common.service.TopicService;
import etcore.webapp.grouptalk.user.object.User;
import etcore.webapp.grouptalk.util.DateUtil;
import etcore.webapp.grouptalk.util.StringDisplay;
import etcore.webapp.grouptalk.util.Symbols;
import etcore.webapp.grouptalk.util.SymmetricEncryptionUtil;

/**
 * This action validates the request and executes the command of showing the
 * calendar page
 * 
 * @author ETCORE GroupTalk Developers
 * 
 */
public class EventAction extends AbstractAction {

	private static final long serialVersionUID = -7342504176949631463L;
	// parameter constants
	public static final String SM = "SM";
	public static final String SY = "SY";
	public static final String CMD_VALUE = "addGmessage";

	// utility constants

	public static final String MINUS_ONE = "-1";
	// utility constants
	public static final String ZERO_STR = "0";
	public static final String START_DATE = "startDate";
	public static final String END_DATE = "endDate";
	public static final String FIRST_STR = "01";
	public static final String GROUP_MAP = "groupMap";
	public static final String START_PID = "startpid";
	public static final String END_PID = "endpid";
	public static final String TARGET_CALENDAR_EVENTS = "targetCalendarEvents";
	public static final String TARGET_TABLE_EVENTS = "targetTableEvents";
	public static final String GROUP_SET = "groupSet";
	public static final String STIME = "stime";
	public static final String INPUT_YEAR = "inputYear";
	public static final String INPUT_MONTH = "inputMonth";
	public static final String SHOW_MINE = "showMine";
	public static final String SHOW_FAVOURITE = "showFavourite";
	public static final String DIRECTORY_ID = "directoryID";

	// forward pages
	public static final String FORWARD_PAGE = "/group/event.jsp";

	@Override
	public int validate(HttpServletRequest request, HttpServletResponse response) {
		// TODO Auto-generated method stub

		return 1;
	}

	@Override
	public String getForward(HttpServletRequest request, int validationResult) {

		return FORWARD_PAGE;
	}

	@Override
	public String getRedirect(HttpServletRequest request, int validationResult) {
		// TODO Auto-generated method stub

		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void execute(int validationResult, HttpServletRequest request,
			HttpServletResponse response) {
		// TODO Auto-generated method stub
		boolean encryptedUrl = false;
		String encryptedUrlStr = Config.getProperty(Config.ENCRYPTEDURL4);
		if (Messages.TRUE.equals(encryptedUrlStr))
			encryptedUrl = true;
		addGmessage(request);
		HttpSession session = request.getSession(true);
		User sessionUser = (User) session.getAttribute(Messages.SESSION_USER);
		String lang = (String) session.getAttribute(Messages.LANG);
		String postfix = Config.getProperty(Config.POSTFIX);
		if (postfix == null)
			postfix = Config.ACTION_POSTFIX;
		int intpageid = 1;
		int unit = 15;
		long all = 0;
		int begin = 0, pagenums = 0;
		String pageid = request.getParameter(PageConstants.PAGEID);
		if (pageid != null)
			intpageid = Integer.parseInt(pageid);
		begin = unit * (intpageid - 1);

		MessageService msgService = new MessageService();

		String inputMonth = request.getParameter(SM);
		String inputYear = request.getParameter(SY);
		String inputDate = request.getParameter("SD");
		String directoryID = request.getParameter(DIRECTORY_ID);
		String showMine = request.getParameter(SHOW_MINE);
		String showFavourite = request.getParameter(SHOW_FAVOURITE);
		String userName = request.getParameter(PageConstants.USERNAME);

		if (userName != null) {
			try {
				userName = new String(userName.getBytes("iso-8859-1"),
						("utf-8"));
				request.setAttribute("eventUserName", userName);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		Integer year = getInputYear(inputYear);
		Integer month = getInputMonth(inputMonth);
		String startDate = getStartDate(inputYear, inputMonth, inputDate);
		String endDate = getEndDate(inputYear, inputMonth);

		List<Object[]> sourceEvents = null;
		if (Messages.TRUE.equalsIgnoreCase(showMine) && sessionUser != null) {
			all = msgService.findSizeOfEvents(startDate, endDate,
					sessionUser.getUserName());
			sourceEvents = msgService.findEvents(startDate, endDate,
					sessionUser.getUserName(), begin, unit, STIME, false);
		} else if (Messages.TRUE.equalsIgnoreCase(showFavourite)
				&& sessionUser != null && userName == null) {
			all = msgService.findSizeOfFavouriteEvents(startDate, endDate,
					sessionUser.getUserName());
			sourceEvents = msgService.findFavouriteEvents(startDate, endDate,
					sessionUser.getUserName(), begin, unit, STIME, false);
		} else if (Messages.TRUE.equalsIgnoreCase(showFavourite)
				&& userName != null) {
			all = msgService.findSizeOfFavouriteEvents(startDate, endDate,
					userName);
			sourceEvents = msgService.findFavouriteEvents(startDate, endDate,
					userName, begin, unit, STIME, false);
		} else if (userName != null) {
			all = msgService.findSizeOfEvents(startDate, endDate, userName);
			sourceEvents = msgService.findEvents(startDate, endDate, userName,
					0, 100, STIME, false);
		} else if (directoryID != null && !Symbols.BLANK.equals(directoryID)) {
			all = msgService.findSizeOfEvents(startDate, endDate, new Integer(
					directoryID));
			sourceEvents = msgService.findEvents(startDate, endDate,
					new Integer(directoryID), begin, unit, STIME, false);
			DirectoryService directoryService = new DirectoryService();
			Directory directory = directoryService.findById(new Integer(
					directoryID));
			GroupService groupService = new GroupService();
			TopicService topicService = new TopicService();
			List<Group> groups = groupService
					.findGroupsByDid(directory.getId());
			for (Group group : groups) {
				List<Topic> topics = topicService.findByProperty(
						PageConstants.GID, group.getId());
				request.setAttribute(group.getId() + PageConstants.TOPICS,
						topics);
			}
			request.setAttribute(directory.getId() + PageConstants.GROUPS,
					groups);
			request.setAttribute("eventDirectory", directory);
		} else {
			if (Messages.LANG_LOCAL.equals(lang)) {
			all = msgService.findSizeOfEvents(true,startDate, endDate);
			sourceEvents = msgService.findEvents(true,startDate, endDate, begin,
					unit, STIME, false);
			}else{
				all = msgService.findSizeOfEvents(false,startDate, endDate);
				sourceEvents = msgService.findEvents(false,startDate, endDate, begin,
						unit, STIME, false);
			}
		}
		pagenums = (int) ((all + unit - 1) / unit);

		List<String> targetCalendarEvents = new ArrayList<String>();
		Map<String, String> groupMap = new HashMap<String, String>();
		Map<String, String> topicMap = new HashMap<String, String>();
		Map<String, String> targetTableEvents = new LinkedHashMap<String, String>();
		Set<String> groupSet = new HashSet<String>();

		transformEvents(sourceEvents, targetCalendarEvents, targetTableEvents,
				groupSet, groupMap, topicMap, encryptedUrl, postfix);

		request.setAttribute(GROUP_MAP, groupMap);
		request.setAttribute(PageConstants.TOPIC_MAP, topicMap);
		request.setAttribute(TARGET_CALENDAR_EVENTS, targetCalendarEvents);
		request.setAttribute(TARGET_TABLE_EVENTS, targetTableEvents);
		request.setAttribute(INPUT_YEAR, year);
		request.setAttribute(INPUT_MONTH, month);
		request.setAttribute(GROUP_SET, groupSet);
		request.setAttribute(START_DATE, startDate);
		request.setAttribute(END_DATE, endDate);
		int startpid = intpageid - 3;
		if (startpid <= 0)
			startpid = 1;
		int endpid = intpageid + 8;
		if (intpageid > 8)
			endpid = intpageid + 6;
		if (endpid >= pagenums)
			endpid = pagenums;

		request.setAttribute(START_PID, startpid);
		request.setAttribute(END_PID, endpid);

		request.setAttribute(PageConstants.PAGENUMS, pagenums);
		request.setAttribute(PageConstants.ALL, all);
		request.setAttribute(PageConstants.UNIT, unit);
		request.setAttribute(PageConstants.INTPAGEID, intpageid);
	}

	private void addGmessage(HttpServletRequest request) {
		String cmd = request.getParameter(PageConstants.CMD);
		if (CMD_VALUE.equals(cmd)) {
			try {

				HttpSession session = request.getSession(true);
				User user = (User) session
						.getAttribute(PageConstants.SESSIONUSER);
				String name = request.getParameter(PageConstants.NAME);

				String tag = request.getParameter(PageConstants.TAG);
				String source = request.getParameter(PageConstants.SOURCE);
				String stime = request.getParameter(PageConstants.STIME);
				String tid = request.getParameter(PageConstants.TID);
				String content = request.getParameter(PageConstants.CONTENT);
				if (tid != null && !tid.equals(MINUS_ONE) && user != null
						&& name != null) {

					Message message = new Message();
					MessageService messageService = new MessageService();

					message.setName(name);

					message.setTid(new Integer(tid));
					message.setFlag(new Integer(0));
					if (content != null) {

						message.setContent(content);

					}

					message.setTag(tag);
					if (source != null)
						message.setSource(source);
					message.setStime(stime);
					message.setUp(new Integer(0));
					message.setAddtime(DateUtil.getTime(Config.getProperty(Config.HOURS_DIFFERENCE)));
					message.setNum(new Integer(0));
					message.setUserName(user.getUserName());
					messageService.save(message);

					String msg = null;
					String lang = (String) session.getAttribute(Messages.LANG);
					if (lang != null && lang.equals(Messages.LANG_EN)) {
						msg = Messages.getELabel(Messages.MSG_SUCCESS);
					} else {
						msg = Messages.getLabel(Messages.MSG_SUCCESS);
					}
					request.setAttribute(PageConstants.MSG, msg);
				}

			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	private void transformEvents(List<Object[]> sourceEvents,
			List<String> targetCalendarEvents,
			Map<String, String> targetTableEvents, Set<String> groupSet,
			Map<String, String> groupMap, Map<String, String> topicMap,
			boolean encryptedUrl, String postfix) {

		if (sourceEvents == null)
			return;
		GroupService groupService = new GroupService();
		TopicService topicService = new TopicService();
		Iterator<Object[]> msi = sourceEvents.iterator();
		int start = -1, end = -1;
		while (msi.hasNext()) {
			Object[] tempm = msi.next();
			Integer tempm_id = (Integer) tempm[0];
			Integer tempm_tid = (Integer) tempm[1];
			String tempm_name = (String) tempm[2];

			String tempm_source = (String) tempm[9];
			String tempm_stime = (String) tempm[10];
			Group group = groupService.findGroupByGmid(tempm_id);
			Topic topic = topicService.findById(tempm_tid);
			groupMap.put(tempm_id.toString(), group.getName());
			topicMap.put(tempm_id.toString(), topic.getName());
			groupSet.add(group.getName());
			StringBuffer dateBuffer = StringDisplay
					.getReminderDateStringBuffer(tempm_source, tempm_stime);
			start = -1;
			end = -1;
			if (tempm_source != null && !Symbols.BLANK.equals(tempm_source)) {
				start = Integer.parseInt(tempm_source.replace(Symbols.MINUS,
						Symbols.BLANK));

			}
			if (tempm_stime != null && !Symbols.BLANK.equals(tempm_stime))
				end = Integer.parseInt(tempm_stime.replace(Symbols.MINUS,
						Symbols.BLANK));

			StringBuffer reminderStringBuffer = new StringBuffer();

			reminderStringBuffer.append("<a href='/group/messagedetail");

			reminderStringBuffer.append(postfix);

			if (encryptedUrl) {
				String urlFragment = SymmetricEncryptionUtil
						.getEncryptedStr("?id=" + tempm_id);
				reminderStringBuffer.append("/~");
				reminderStringBuffer.append(urlFragment);
			} else {
				reminderStringBuffer.append("?id=");
				reminderStringBuffer.append(tempm_id);
			}
			reminderStringBuffer.append("' ");
			if (!visible(tempm_stime))
				reminderStringBuffer.append(" style='color: #999999' ");
			reminderStringBuffer.append("target=_blank>");

			reminderStringBuffer.append("[");
			reminderStringBuffer.append(dateBuffer.toString());
			reminderStringBuffer.append(" ");
			reminderStringBuffer.append(group.getName());
			reminderStringBuffer.append("]");
			reminderStringBuffer.append(StringDisplay.showSizedString(
					tempm_name.replace("*", ""), 60));
			reminderStringBuffer.append("</a>");
			targetTableEvents.put(tempm_id.toString(),
					reminderStringBuffer.toString());

			if (start == -1 && end != -1)
				start = end;
			if (start != -1 && end == -1)
				end = start;

			if (start != -1 && end != -1)
				if (start != end) {
					int left = end % 100;
					int monthStart = end - left + 1;
					if (start < monthStart)
						start = monthStart;
				}
			for (int n = start; n <= end; n++) {
				String dateStr = n + "*";
				reminderStringBuffer.insert(0, dateStr);
				targetCalendarEvents.add(reminderStringBuffer.toString());
				reminderStringBuffer.delete(0, dateStr.length());
			}

		}
	}

	@SuppressWarnings("deprecation")
	private int getInputYear(String inputYear) {
		Date today = new Date();
		int result = today.getYear() + 1900;
		if (inputYear != null)
			result = Integer.parseInt(inputYear);
		return result;
	}

	@SuppressWarnings("deprecation")
	private int getInputMonth(String inputMonth) {
		Date today = new Date();
		int result = 0;
		if (inputMonth != null)
			result = Integer.parseInt(inputMonth) - 1;
		else
			result = today.getMonth();
		return result;
	}

	@SuppressWarnings("deprecation")
	private String getStartDate(String inputYear, String inputMonth,
			String inputDate) {
		Date today = new Date();
		StringBuffer startDateBuffer = new StringBuffer();
		StringBuffer monthBuffer = new StringBuffer();
		int thisYear = today.getYear() + 1900;
		if (inputMonth != null)
			monthBuffer.append((Integer.parseInt(inputMonth)));
		else
			monthBuffer.append((today.getMonth() + 1));
		if (monthBuffer.length() == 1) {
			monthBuffer.insert(0, ZERO_STR);
		}
		if (inputYear == null)
			inputYear = Integer.toString(thisYear);

		startDateBuffer.append(inputYear);
		startDateBuffer.append(Symbols.MINUS);
		startDateBuffer.append(monthBuffer.toString());
		startDateBuffer.append(Symbols.MINUS);
		if (inputDate != null) {
			startDateBuffer.append(inputDate);
		} else if ((inputYear == null || Integer.parseInt(inputYear) - thisYear == 0)
				&& (inputMonth == null || Integer.parseInt(inputMonth)
						- today.getMonth() == 0))
			startDateBuffer.append(today.getDate());

		else
			startDateBuffer.append(FIRST_STR);
		return startDateBuffer.toString();
	}

	@SuppressWarnings("deprecation")
	private String getEndDate(String inputYear, String inputMonth) {
		Date today = new Date();
		int thisYear = today.getYear() + 1900;
		StringBuffer endDateBuffer = new StringBuffer();
		StringBuffer monthBuffer = new StringBuffer();
		if (inputMonth != null)
			monthBuffer.append((Integer.parseInt(inputMonth) + 1));
		else
			monthBuffer.append((today.getMonth() + 2));

		if (inputYear == null)
			inputYear = Integer.toString(thisYear);

		int endMonth = Integer.parseInt(monthBuffer.toString());
		int endYear = Integer.parseInt(inputYear);
		if (endMonth > 12) {
			endYear = endYear + 1;
			endMonth = 1;
		}
		endDateBuffer.append(endYear);
		endDateBuffer.append(Symbols.MINUS);
		if (endMonth < 10)
			endDateBuffer.append(ZERO_STR);
		endDateBuffer.append(endMonth);
		endDateBuffer.append(Symbols.MINUS);
		endDateBuffer.append(FIRST_STR);

		return endDateBuffer.toString();
	}

	@SuppressWarnings("deprecation")
	private boolean visible(String endDate) {

		Date today = new Date();
		int thisYear = today.getYear() + 1900;
		boolean visible = true;
		if (endDate != null && endDate.length() == 10) {

			String tmpYear = endDate.substring(0, 4);
			String tmpMonth = endDate.substring(5, 7);
			String tmpDay = endDate.substring(8);
			if (thisYear > Integer.parseInt(tmpYear))
				visible = false;
			if (visible && thisYear == Integer.parseInt(tmpYear)
					&& today.getMonth() > (Integer.parseInt(tmpMonth) - 1))
				visible = false;
			if (visible && thisYear == Integer.parseInt(tmpYear)
					&& today.getMonth() == (Integer.parseInt(tmpMonth) - 1)
					&& today.getDate() > Integer.parseInt(tmpDay))
				visible = false;

		}
		return visible;

	}

	@Override
	public boolean isForward(int validationResult) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public boolean enablePostLoad() {
		// TODO Auto-generated method stub
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see etcore.webapp.grouptalk.controller.action.AbstractAction#
	 * buildSelfContextAndAttributes(int, javax.servlet.http.HttpServletRequest)
	 */
	@Override
	public List<String> getNamespacesOfMessages(HttpServletRequest request) {
		// TODO Auto-generated method stub
		List<String> namespaces = new ArrayList<String>();
		namespaces.add(MessageNamespaces.EVENT);
		return namespaces;
	}

}
